package org.ciallo.easytokencore.strategy;

import org.ciallo.easytokencore.annotation.handler.EasyAnnotationHandlerInterface;
import org.ciallo.easytokencore.annotation.handler.EasyCheckLoginHandler;
import org.ciallo.easytokencore.annotation.handler.EasyTokenAutoInjectHandler;
import org.ciallo.easytokencore.annotation.handler.EasyTokenAutoRefreshHandler;
import org.ciallo.easytokencore.interceptor.EasyAnnotationInterceptor;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Easy-Token 注解鉴权策略核心类
 *
 * <p>主要功能：</p>
 * <ul>
 *   <li>管理所有注解处理器</li>
 *   <li>提供注解注册和移除功能</li>
 *   <li>实现方法级别的注解校验</li>
 *   <li>支持自定义注解处理器扩展</li>
 * </ul>
 *
 * <p>典型使用场景：</p>
 * <ol>
 *   <li>通过registerAnnotationHandler注册自定义注解处理器</li>
 *   <li>在拦截器中调用checkMethodAnnotation进行注解校验</li>
 * </ol>
 *
 * @Description: Easy-Token 注解鉴权策略核心实现
 * @Author: Jukomu
 * @Package: org.ciallo.easytokencore.strategy
 * @Project: easy-token-demo
 * @Version: 1.0.0
 * @name: EasyAnnotationStrategy
 * @Date: 2025/5/6-22:35
 * @Filename: EasyAnnotationStrategy
 * @see EasyAnnotationHandlerInterface
 * @see EasyAnnotationInterceptor
 */
public class EasyAnnotationStrategy {

    public EasyAnnotationStrategy() {
        registerDefaultAnnotationHandler();
    }

    /**
     * 全局单例引用
     */
    public static final EasyAnnotationStrategy instance = new EasyAnnotationStrategy();

    /**
     * 注解处理器集合
     */
    public Map<Class<?>, EasyAnnotationHandlerInterface<?>> annotationHandlerMap = new LinkedHashMap<>();

    /**
     * 注册所有默认的注解处理器
     */
    public void registerDefaultAnnotationHandler() {
        registerAnnotationHandler(new EasyCheckLoginHandler());
        registerAnnotationHandler(new EasyTokenAutoRefreshHandler());
        registerAnnotationHandler(new EasyTokenAutoInjectHandler());
    }

    /**
     * 注册一个注解处理器
     */
    public void registerAnnotationHandler(EasyAnnotationHandlerInterface<?> handler) {
        annotationHandlerMap.put(handler.getHandlerAnnotationClass(), handler);
    }

    /**
     * 注册一个注解处理器，到首位
     */
    public void registerAnnotationHandlerToFirst(EasyAnnotationHandlerInterface<?> handler) {
        Map<Class<?>, EasyAnnotationHandlerInterface<?>> newMap = new LinkedHashMap<>();
        newMap.put(handler.getHandlerAnnotationClass(), handler);
        newMap.putAll(annotationHandlerMap);
        this.annotationHandlerMap = newMap;
    }

    /**
     * 移除一个注解处理器
     */
    public void removeAnnotationHandler(Class<?> cls) {
        annotationHandlerMap.remove(cls);
    }

    /**
     * 请求方法处理前执行注解对应操作
     * 对一个 [Method] 对象进行注解校验 （注解鉴权内部实现）
     */
    @SuppressWarnings("unchecked")
    public void checkMethodAnnotationPreHandle(Method method) {
        // 遍历所有的注解处理器，检查此 method 是否具有这些指定的注解
        for (Map.Entry<Class<?>, EasyAnnotationHandlerInterface<?>> entry : annotationHandlerMap.entrySet()) {

            // 先校验 Method 所属 Class 上的注解
            Annotation classTakeAnnotation = instance.getAnnotation(method.getDeclaringClass(), (Class<Annotation>) entry.getKey());
            if (classTakeAnnotation != null) {
                entry.getValue().checkPreHandle(classTakeAnnotation, method);
            }

            // 再校验 Method 上的注解
            Annotation methodTakeAnnotation = instance.getAnnotation(method, (Class<Annotation>) entry.getKey());
            if (methodTakeAnnotation != null) {
                entry.getValue().checkPreHandle(methodTakeAnnotation, method);
            }
        }
    }

    /**
     * 请求方法处理完成后、视图渲染之前执行注解对应操作
     * 对一个 [Method] 对象进行注解校验 （注解鉴权内部实现）
     */
    @SuppressWarnings("unchecked")
    public void checkMethodAnnotationPostHandle(Method method) {
        // 遍历所有的注解处理器，检查此 method 是否具有这些指定的注解
        for (Map.Entry<Class<?>, EasyAnnotationHandlerInterface<?>> entry : annotationHandlerMap.entrySet()) {

            // 先校验 Method 所属 Class 上的注解
            Annotation classTakeAnnotation = instance.getAnnotation(method.getDeclaringClass(), (Class<Annotation>) entry.getKey());
            if (classTakeAnnotation != null) {
                entry.getValue().checkPostHandle(classTakeAnnotation, method);
            }

            // 再校验 Method 上的注解
            Annotation methodTakeAnnotation = instance.getAnnotation(method, (Class<Annotation>) entry.getKey());
            if (methodTakeAnnotation != null) {
                entry.getValue().checkPostHandle(methodTakeAnnotation, method);
            }
        }
    }

    /**
     * 在整个请求完成时执行注解对应操作
     * 对一个 [Method] 对象进行注解校验 （注解鉴权内部实现）
     */
    public void checkMethodAnnotationAfterCompletion(Method method) {
        // 遍历所有的注解处理器，检查此 method 是否具有这些指定的注解
        for (Map.Entry<Class<?>, EasyAnnotationHandlerInterface<?>> entry : annotationHandlerMap.entrySet()) {

            // 先校验 Method 所属 Class 上的注解
            Annotation classTakeAnnotation = instance.getAnnotation(method.getDeclaringClass(), (Class<Annotation>) entry.getKey());
            if (classTakeAnnotation != null) {
                entry.getValue().checkAfterCompletion(classTakeAnnotation, method);
            }

            // 再校验 Method 上的注解
            Annotation methodTakeAnnotation = instance.getAnnotation(method, (Class<Annotation>) entry.getKey());
            if (methodTakeAnnotation != null) {
                entry.getValue().checkAfterCompletion(methodTakeAnnotation, method);
            }
        }
    }


    /**
     * 从元素上获取注解
     */
    public Annotation getAnnotation(AnnotatedElement element, Class<? extends Annotation> annotationClass) {
        // 默认使用jdk的注解处理器
        return element.getAnnotation(annotationClass);
    }

    /**
     * 判断一个 Method 或其所属 Class 是否包含指定注解
     */
    public Boolean isAnnotationPresent(Method method, Class<? extends Annotation> annotationClass) {
        return instance.getAnnotation(method, annotationClass) != null ||
                instance.getAnnotation(method.getDeclaringClass(), annotationClass) != null;
    }
}
